/******************************************************************************
* Prog#: 10, Q1
* Name (Last, First): Pincock, Dallin
* Linux Login: drpincoc
*
*
* Function: ExitProg
* Does a simple exit of the program.
*
* Pseudocode:
* exit(0)
*
*
* Function: PrintMatrix
* Prints the elements of a 2D matrix as rows x columns
*
* Pseudocode:
* for (i = 0; i < rows; i++)
*     for (j = 0; j < columns; j++)
*         print M[i][j]
*
*
* Function: MultTwoMatrices
* Input two matrices (in this case, M1 and M4) and output a matrix that is the
* product of the first two (in this case, M1 * M4 = M5)
* Function assumes (columns of first matrix == rows of second matrix)
* and third matrix is rows of first matrix by columns of second matrix
*
* Pseudocode:
* first matrix is c*p, second is p*d
* for (i = 0; i < p; i++)
*     for (j = 0; j < d; j++)
*         for (k = 0; k < p; k++)
*             sum += M1[i][k] * M4[k][j] (sum starts at 0)
*             M5[i][j] = sum
*
*
* Function: AddTwoMatrices
* Input two matrices (M1 and M2 here) and output a matrix that is the sum of
* the first two (in this case, M1 + M2 = M3)
* Function assumes dimensions of all the matrices are equal
*
* Pseudocode:
* for (i = 0; i < rows; i++)
*     for (j = 0; j < columns; j++)
*         M3[i][j] = M1[i][j] + M2[i][j]
*
*
* Function: InitializeMatrices
* Set initial values of matrices (M1, M2, M4 are non-empty, M3 and M5 zeroed)
*
* Pseudocode:
* Very simple, we're setting the values of matrices to ones given in the
* assignment. Self explainatory.
*
*
* Function: UserMenu
* Display a user menu
*
* Pseudocode:
* print menu, like so:
* 1) Exit
* 2) Initialize all matrices
* 3) Add two matrices
* 4) Multiply two matrices
* 5) Print a matrix
*
*
* Function: main
* a driver program
*
* Pseudocode:
* handle input and output accordingly
******************************************************************************/

/******************************************************************************
* This is an added comment for Assignment 2 for CS 680. Friggin' Subversion.
* This is a change.
******************************************************************************/

#include "Prog10q1.h"

void ExitProg()
{
    exit(0);
}

void PrintMatrix(int M[], int rows, int columns)
{
    int i;
    int j;
    for (i = 0; i < rows; i++) {
        for (j = 0; j < columns; j++) {
            printf("%5d", M[(i*columns)+j]);
        }
        printf("\n");
    }
}

void MultTwoMatrices(int (*M1)[4][2], int (*M4)[2][3], int (*M5)[4][3])
{
    int i;
    int j;
    int k;
    int sum = 0;
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 3; j++) {
            for (k = 0; k < 2; k++) {
                sum += (*M1)[i][k] * (*M4)[k][j];
            }
            (*M5)[i][j] = sum;
            sum = 0;
        }
    }
}

void AddTwoMatrices(int (*M1)[4][2], int (*M2)[4][2], int (*M3)[4][2])
{
    int i;
    int j;
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 2; j++) {
            (*M3)[i][j] = (*M1)[i][j] + (*M2)[i][j];
        }
    }
}

void InitializeMatrices(int (*M1)[4][2], int (*M2)[4][2], int (*M3)[4][2],
                        int (*M4)[2][3], int (*M5)[4][3])
{
    int i;
    int j;
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 2; j++) {
            (*M1)[i][j] = (i * 2) + j + 1;
        }
    }
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 2; j++) {
            (*M2)[i][j] = 8 - (i * 2) - j;
        }
    }
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 2; j++) {
            (*M3)[i][j] = 0;
        }
    }
    for (i = 0; i < 2; i++) {
        for (j = 0; j < 3; j++) {
            (*M4)[i][j] = 2;
        }
    }
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 3; j++) {
            (*M5)[i][j] = 0;
        }
    }
}

char UserMenu()
{
    printf("Welcome to CS460 (Fall 2013) HW-10 Q1 Solution!\n");
    printf("Options:\n");
    printf("1) Exit\n");
    printf("2) Initialize all matrices\n");
    printf("3) Add two matrices\n");
    printf("4) Multiply two matrices\n");
    printf("5) Print a matrix\n");
    printf("Please enter your option > ");
    char input = getchar();
    getchar();
    return input;
}

int main()
{
    char input = '0';
    int M1[4][2];
    int (*ptrM1)[4][2] = &M1;
    int M2[4][2];
    int (*ptrM2)[4][2] = &M2;
    int M3[4][2];
    int (*ptrM3)[4][2] = &M3;
    int M4[2][3];
    int (*ptrM4)[2][3] = &M4;
    int M5[4][3];
    int (*ptrM5)[4][3] = &M5;
    while (input != '1') {
        input = UserMenu();
        if (input == '1')
            ExitProg();
        else if (input == '2')
            InitializeMatrices(ptrM1, ptrM2, ptrM3, ptrM4, ptrM5);
        else if (input == '3')
            AddTwoMatrices(ptrM1, ptrM2, ptrM3);
        else if (input == '4')
            MultTwoMatrices(ptrM1, ptrM4, ptrM5);
        else if (input == '5') {
            char matrixInput = '0';
            printf("\nInput a matrix (1-5): ");
            matrixInput = getchar();
            getchar();
            if (matrixInput == '1') {
                int *ptrM1 = M1[0];
                PrintMatrix(ptrM1, 4, 2);
            }
            else if (matrixInput == '2') {
                int *ptrM2 = M2[0];
                PrintMatrix(ptrM2, 4, 2);
            }
            else if (matrixInput == '3') {
                int *ptrM3 = M3[0];
                PrintMatrix(ptrM3, 4, 2);
            }
            else if (matrixInput == '4') {
                int *ptrM4 = M4[0];
                PrintMatrix(ptrM4, 2, 3);
            }
            else if (matrixInput == '5') {
                int *ptrM5 = M5[0];
                PrintMatrix(ptrM5, 4, 3);
            }
            else
                printf("Not a valid option!\n");
        }
    }
    return 0;
}
